home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 January: Mac OS SDK / Dev.CD Jan 97 SDK2.toast / Development Kits (Disc 2) / OpenDoc / OpenDoc Development / Debugging Support / OpenDoc™ Source Code / Storage / LinkB.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  22.7 KB  |  883 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        LinkB.cpp
  3.  
  4.     Contains:    Implementation of ODBaseLink class
  5.  
  6.     Owned by:    Craig Carper
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.          <2>     5/24/96    jpa        1246074: SOM_CATCH --> SOM_TRY..SOM_ENDTRY
  13.          
  14.     To Do:
  15.     In Progress:
  16.         
  17. */
  18.  
  19. #define VARIABLE_MACROS
  20.  
  21. #define ODBaseLink_Class_Source
  22. #include <LinkB.xih>
  23.  
  24. #ifndef _EXCEPT_
  25. #include <Except.h>
  26. #endif
  27.  
  28. #ifndef _ODMEMORY_
  29. #include <ODMemory.h>
  30. #endif
  31.  
  32. #ifndef _CONSTDEF_
  33. #include <ConstDef.h>
  34. #endif
  35.  
  36. #ifndef _LINKDLGS_
  37. #include <LinkDlgs.h>
  38. #endif
  39.  
  40. #ifndef SOM_ODLinkSource_xh
  41. #include <LinkSrc.xh>
  42. #endif
  43.  
  44. #ifndef _LINKLIST_
  45. #include <LinkList.h>
  46. #endif
  47.  
  48. #ifndef SOM_ODPart_xh
  49. #include <Part.xh>
  50. #endif
  51.  
  52. #ifndef SOM_ODFrame_xh
  53. #include <Frame.xh>
  54. #endif
  55.  
  56. #ifndef SOM_ODSession_xh
  57. #include <ODSessn.xh>
  58. #endif
  59.  
  60. #ifndef SOM_ODArbitrator_xh
  61. #include <Arbitrat.xh>
  62. #endif
  63.  
  64. #ifndef SOM_ODWindowState_xh
  65. #include <WinStat.xh>
  66. #endif
  67.  
  68. #ifndef SOM_Module_OpenDoc_Foci_defined
  69. #include <Foci.xh>
  70. #endif
  71.  
  72. #ifndef SOM_ODContainer_xh
  73. #include <ODCtr.xh>
  74. #endif
  75.  
  76. #ifndef SOM_ODDocument_xh
  77. #include <Document.xh>
  78. #endif
  79.  
  80. #ifndef SOM_ODDraft_xh
  81. #include <Draft.xh>
  82. #endif
  83.  
  84. #ifndef SOM_ODStorageUnit_xh
  85. #include <StorageU.xh>
  86. #endif
  87.  
  88. #ifndef SOM_Module_OpenDoc_StdProps_defined
  89. #include <StdProps.xh>
  90. #endif
  91.  
  92. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  93. #include <StdTypes.xh>
  94. #endif
  95.  
  96. #ifndef __ERRORS__
  97. #include <Errors.h>
  98. #endif
  99.  
  100. #ifndef _ODUTILS_
  101. #include <ODUtils.h>
  102. #endif
  103.  
  104. #ifndef _STDTYPIO_
  105. #include <StdTypIO.h>
  106. #endif
  107.  
  108. #ifndef _DOCUTILS_
  109. #include <DocUtils.h>
  110. #endif
  111.  
  112. #ifndef _STORUTIL_
  113. #include <StorUtil.h>
  114. #endif
  115.  
  116. #ifndef _ODDEBUG_
  117. #include <ODDebug.h>
  118. #endif
  119.  
  120. #ifndef _TEMPOBJ_
  121. #include "TempObj.h"
  122. #endif
  123.  
  124. #pragma segment ODBaseLink
  125.  
  126. //==============================================================================
  127. // Local Classes
  128. //==============================================================================
  129.  
  130. //------------------------------------------------------------------------------
  131. // Class ODPartLink
  132. //------------------------------------------------------------------------------
  133.  
  134. class ODPartLink : public Link {
  135.     public:
  136.         ODPartLink(ODPart* thePart) {fPart = thePart;}
  137.         virtual ~ODPartLink()        {}
  138.         ODPart*    GetPart()            { return fPart;}
  139.     
  140.     private:
  141.         ODPart*    fPart;
  142. };
  143.  
  144. //------------------------------------------------------------------------------
  145. // Class ODPartList
  146. //------------------------------------------------------------------------------
  147.  
  148. class ODPartList
  149. {
  150.     friend class ODPartListIterator;
  151.     
  152.     public:
  153.  
  154.         ODPartList()            {}
  155.         virtual ~ODPartList()    {this->RemoveAllParts(somGetGlobalEnvironment());}
  156.  
  157.         virtual ODBoolean    ContainsPart(Environment *ev, ODPart* thePart);
  158.         virtual ODBoolean    AddPart(Environment *ev, ODPart* thePart);
  159.         virtual void        AddPartList(Environment *ev, ODPartList* thePartList);
  160.         virtual void        RemovePart(Environment *ev, ODPart* thePart);
  161.         virtual void        RemovePartList(Environment *ev, ODPartList* thePartList);
  162.         virtual void        RemoveAllParts(Environment *ev);
  163.  
  164.     private:
  165.  
  166.         LinkedList    fImplementation;
  167. };
  168.  
  169. //------------------------------------------------------------------------------
  170. // Class ODPartListIterator
  171. //------------------------------------------------------------------------------
  172.  
  173. class ODPartListIterator
  174. {
  175. public:
  176.  
  177.     ODPartListIterator(ODPartList* partList)
  178.         : fIterator(&(partList->fImplementation))
  179.         {}
  180.     ODVMethod ~ODPartListIterator()
  181.         {}
  182.     
  183.     ODMethod ODPart* First();
  184.     ODMethod ODPart* Next();
  185.     ODMethod ODBoolean IsNotComplete();
  186.     
  187. private:
  188.     
  189.     LinkedListIterator fIterator;
  190.     
  191. };
  192.  
  193. //------------------------------------------------------------------------------
  194. // ODPartList::ContainsPart
  195. //------------------------------------------------------------------------------
  196.  
  197. ODBoolean ODPartList::ContainsPart(Environment *ev, ODPart* thePart)
  198. {
  199.     ODBoolean result = kODFalse;
  200.     ODPartListIterator iter(this);
  201.  
  202.     for (ODPart* part = iter.First(); (result == kODFalse) && iter.IsNotComplete(); part = iter.Next())
  203.     {
  204.         result = ODObjectsAreEqual(ev, part, thePart);
  205.     }
  206.  
  207.     return result;
  208. }
  209.  
  210. //------------------------------------------------------------------------------
  211. // ODPartList::AddPart
  212. //------------------------------------------------------------------------------
  213.  
  214. ODBoolean ODPartList::AddPart(Environment *ev, ODPart* thePart)
  215. {
  216.     ODBoolean notPresent = !this->ContainsPart(ev, thePart);
  217.     if ( notPresent )
  218.     {
  219.         ODPartLink* aLink = new ODPartLink(thePart);
  220.         thePart->Acquire(ev);
  221.         fImplementation.AddLast(aLink);
  222.     }
  223.     
  224.     return notPresent;
  225. }
  226.  
  227. //------------------------------------------------------------------------------
  228. // ODPartList::AddPartList
  229. //------------------------------------------------------------------------------
  230.  
  231. void ODPartList::AddPartList(Environment *ev, ODPartList* thePartList)
  232. {
  233.     if ( thePartList )
  234.     {
  235.         ODPartListIterator iter(thePartList);
  236.     
  237.         for (ODPart* thePart = iter.First(); iter.IsNotComplete(); thePart = iter.Next())
  238.         {
  239.             this->AddPart(ev, thePart);
  240.         }
  241.     }
  242. }
  243.  
  244. //------------------------------------------------------------------------------
  245. // ODPartList::RemovePart
  246. //------------------------------------------------------------------------------
  247.  
  248. void ODPartList::RemovePart(Environment *ev, ODPart* thePart)
  249. {
  250.     LinkedListIterator iter(&fImplementation);
  251.  
  252.     ODPartLink* aLink = (ODPartLink*)iter.First();
  253.     while (aLink != NULL)
  254.     {
  255.         ODPart* part = aLink->GetPart();
  256.         if ( ODObjectsAreEqual(ev, part, thePart) )
  257.         {
  258.             fImplementation.Remove(*aLink);
  259.             aLink = NULL;
  260.             part->Release(ev);
  261.         }
  262.         else
  263.             aLink = (ODPartLink*)iter.Next();
  264.     }
  265. }
  266.  
  267. //------------------------------------------------------------------------------
  268. // ODPartList::RemovePartList
  269. //------------------------------------------------------------------------------
  270.  
  271. void ODPartList::RemovePartList(Environment *ev, ODPartList* thePartList)
  272. {
  273.     if ( thePartList )
  274.     {
  275.         ODPartListIterator iter(thePartList);
  276.     
  277.         for (ODPart* thePart = iter.First(); iter.IsNotComplete(); thePart = iter.Next())
  278.         {
  279.             this->RemovePart(ev, thePart);
  280.         }
  281.     }
  282. }
  283.  
  284. //------------------------------------------------------------------------------
  285. // ODPartList::RemoveAllParts
  286. //------------------------------------------------------------------------------
  287.  
  288. void ODPartList::RemoveAllParts(Environment *ev)
  289. {
  290.     ODPartLink* aLink = (ODPartLink*) fImplementation.RemoveFirst();
  291.     while (aLink != kODNULL)
  292.     {
  293.         ODPart* part = aLink->GetPart();
  294.         part->Release(ev);
  295.         delete aLink;
  296.         aLink = (ODPartLink*) fImplementation.RemoveFirst();
  297.     }
  298. }
  299.  
  300. //------------------------------------------------------------------------------
  301. // ODPartListIterator::First
  302. //------------------------------------------------------------------------------
  303.  
  304. ODPart* ODPartListIterator::First()
  305. {
  306.     ODPart* part = kODNULL;
  307.     ODPartLink* partLink = (ODPartLink*) fIterator.First();
  308.     
  309.     if ( partLink )
  310.         part = partLink->GetPart();
  311.     
  312.     return part;
  313. }
  314.  
  315. //------------------------------------------------------------------------------
  316. // ODPartListIterator::Next
  317. //------------------------------------------------------------------------------
  318.  
  319. ODPart* ODPartListIterator::Next()
  320. {
  321.     ODPart* part = kODNULL;
  322.     ODPartLink* partLink = (ODPartLink*) fIterator.Next();
  323.     
  324.     if ( partLink )
  325.         part = partLink->GetPart();
  326.     
  327.     return part;
  328. }
  329.  
  330. //------------------------------------------------------------------------------
  331. // ODPartListIterator::IsNotComplete
  332. //------------------------------------------------------------------------------
  333.  
  334. ODBoolean ODPartListIterator::IsNotComplete()
  335. {
  336.     return fIterator.IsNotComplete();
  337. }
  338.  
  339. //==============================================================================
  340. // ODBaseLink
  341. //==============================================================================
  342.  
  343. //------------------------------------------------------------------------------
  344. // ODBaseLink: somUninit
  345. //------------------------------------------------------------------------------
  346.  
  347. SOM_Scope void  SOMLINK ODBaseLinksomUninit(ODBaseLink *somSelf)
  348. {
  349.     /* ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf); */
  350.     ODBaseLinkMethodDebug("ODBaseLink","somUninit");
  351.  
  352.     parent_somUninit(somSelf);
  353. }
  354.  
  355. //------------------------------------------------------------------------------
  356. // ODBaseLink: InitBaseLink
  357. //------------------------------------------------------------------------------
  358.  
  359. SOM_Scope void  SOMLINK ODBaseLinkInitBaseLink(ODBaseLink *somSelf, Environment *ev,
  360.         ODStorageUnit* storageUnit)
  361. {
  362.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  363.     ODBaseLinkMethodDebug("ODBaseLink","InitBaseLink");
  364.  
  365.     SOM_TRY
  366.  
  367.     /* Moved from somInit. SOM itself sets fields to zero
  368.     _fPartList = (ODPartList*) kODNULL;
  369.     _fLinkSource = (ODLinkSource*) kODNULL;
  370.     _fDirty = kODFalse;
  371.     _fIterationInProgress = kODFalse;
  372.     _fRestartIteration = kODFalse;
  373.     */
  374.     somSelf->InitPersistentObject(ev, storageUnit);
  375.  
  376.     _fPartList = new ODPartList();
  377.  
  378.     ODStorageUnit* su = somSelf->GetStorageUnit(ev);
  379.     ODSUAddPropValue(ev, su, kODPropLinkSource, kODWeakStorageUnitRef);
  380.  
  381.     somSelf->SetBaseLinkDirty(ev);
  382.  
  383.     SOM_CATCH_ALL
  384.     SOM_ENDTRY
  385. }
  386.  
  387. //------------------------------------------------------------------------------
  388. // ODBaseLink: InitBaseLinkFromStorage
  389. //------------------------------------------------------------------------------
  390.  
  391. SOM_Scope void  SOMLINK ODBaseLinkInitBaseLinkFromStorage(ODBaseLink *somSelf, Environment *ev,
  392.         ODStorageUnit* storageUnit)
  393. {
  394.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  395.     ODBaseLinkMethodDebug("ODBaseLink","InitBaseLinkFromStorage");
  396.  
  397.     SOM_TRY
  398.  
  399.     /* Moved from somInit. SOM itself sets fields to zero
  400.     _fPartList = (ODPartList*) kODNULL;
  401.     _fLinkSource = (ODLinkSource*) kODNULL;
  402.     _fDirty = kODFalse;
  403.     _fIterationInProgress = kODFalse;
  404.     _fRestartIteration = kODFalse;
  405.     */
  406.     somSelf->InitPersistentObjectFromStorage(ev, storageUnit);
  407.  
  408.     _fPartList = new ODPartList();
  409.     
  410.     if ( storageUnit->Exists(ev, kODPropLinkSource, 0, 0) )
  411.     {
  412.         ODID linkSourceID = ODGetWeakSURefProp(ev, storageUnit, kODPropLinkSource, kODWeakStorageUnitRef);
  413.         if ( linkSourceID == kODNULLID )
  414.             somSelf->SetBaseLinkDirty(ev);
  415.         else
  416.             _fLinkSource = storageUnit->GetDraft(ev)->AcquireLinkSource(ev, linkSourceID);
  417.     }
  418.  
  419.     SOM_CATCH_ALL
  420.     SOM_ENDTRY
  421. }
  422.  
  423. //------------------------------------------------------------------------------
  424. // ODBaseLink: Externalize (OVERRIDE)
  425. //------------------------------------------------------------------------------
  426.  
  427. SOM_Scope void  SOMLINK ODBaseLinkExternalize(ODBaseLink *somSelf, Environment *ev)
  428. {
  429.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  430.     ODBaseLinkMethodDebug("ODBaseLink","Externalize");
  431.  
  432.     SOM_TRY
  433.  
  434.     parent_Externalize(somSelf,ev);
  435.  
  436.     if ( _fDirty )
  437.     {
  438.         ODStorageUnit* su = somSelf->GetStorageUnit(ev);
  439.     
  440.         if ( _fLinkSource == (ODLinkSource*) kODNULL )
  441.             ODSURemoveProperty(ev, su, kODPropLinkSource);
  442.         else
  443.             ODSetWeakSURefProp(ev, su, kODPropLinkSource, kODWeakStorageUnitRef, _fLinkSource->GetID(ev));
  444.  
  445.         _fDirty = kODFalse;
  446.     }
  447.  
  448.     SOM_CATCH_ALL
  449.     SOM_ENDTRY
  450. }
  451.  
  452. //------------------------------------------------------------------------------
  453. // ODBaseLink: CloneInto (OVERRIDE)
  454. //------------------------------------------------------------------------------
  455.  
  456. SOM_Scope void  SOMLINK ODBaseLinkCloneInto(ODBaseLink *somSelf, Environment *ev,
  457.         ODDraftKey key,
  458.         ODStorageUnit* toSU,
  459.         ODFrame* scopeFrame)
  460. {
  461.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  462.     ODBaseLinkMethodDebug("ODBaseLink","CloneInto");
  463.  
  464.     SOM_TRY
  465.     
  466.     // If one of our properties already exists, this object has been cloned already
  467.     if ( toSU->Exists(ev, kODPropLinkSource, kODWeakStorageUnitRef, 0) )
  468.         return;
  469.  
  470.     parent_CloneInto(somSelf, ev, key, toSU, scopeFrame);
  471.  
  472.     if ( _fLinkSource != (ODLinkSource*) kODNULL )
  473.     {
  474.         ODDraft* draft = somSelf->GetStorageUnit(ev)->GetDraft(ev);
  475.         ODID clonedLinkSourceID = draft->WeakClone(ev, key, _fLinkSource->GetID(ev), 0, 
  476.                                                 (scopeFrame ? scopeFrame->GetID(ev) : 0));
  477.     
  478.         ODSetWeakSURefProp(ev, toSU, kODPropLinkSource, kODWeakStorageUnitRef, clonedLinkSourceID);
  479.     }
  480.  
  481.     SOM_CATCH_ALL
  482.     SOM_ENDTRY
  483. }
  484.  
  485. //------------------------------------------------------------------------------
  486. // ODBaseLink: ReleaseAll (OVERRIDE)
  487. //------------------------------------------------------------------------------
  488.  
  489. SOM_Scope void  SOMLINK ODBaseLinkReleaseAll(ODBaseLink *somSelf, Environment *ev)
  490. {
  491.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  492.     ODBaseLinkMethodDebug("ODBaseLink","ReleaseAll");
  493.  
  494.     SOM_TRY
  495.  
  496.     parent_ReleaseAll(somSelf,ev);
  497.  
  498.     ODReleaseObject(ev, _fLinkSource);
  499.  
  500.     // Release all part references stored in the list of registered parts
  501.     ODDeleteObject(_fPartList);
  502.  
  503.     SOM_CATCH_ALL
  504.     SOM_ENDTRY
  505. }
  506.  
  507. //------------------------------------------------------------------------------
  508. // ODBaseLink: SetBaseLinkDirty
  509. //------------------------------------------------------------------------------
  510.  
  511. SOM_Scope void  SOMLINK ODBaseLinkSetBaseLinkDirty(ODBaseLink *somSelf, Environment *ev)
  512. {
  513.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  514.     ODBaseLinkMethodDebug("ODBaseLink","SetBaseLinkDirty");
  515.  
  516.     SOM_TRY    
  517.         _fDirty = kODTrue;
  518.  
  519.         ODDraft* draft = somSelf->GetStorageUnit(ev)->GetDraft(ev);
  520.         if ( draft->GetPermissions(ev) != kODDPReadOnly )
  521.             draft->SetChangedFromPrev(ev);
  522.     SOM_CATCH_ALL
  523.     SOM_ENDTRY
  524. }
  525.  
  526. //------------------------------------------------------------------------------
  527. // ODBaseLink::ShowLinkDestinationInfo
  528. //------------------------------------------------------------------------------
  529.  
  530. SOM_Scope ODBoolean  SOMLINK ODBaseLinkShowLinkDestinationInfo(ODBaseLink *somSelf, Environment *ev,
  531.         ODFacet* facet,
  532.         ODLinkInfo* info,
  533.         ODBoolean changesAllowed,
  534.         ODLinkInfoResult* infoResult)
  535. {
  536.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  537.     ODBaseLinkMethodDebug("ODBaseLink","ShowLinkDestinationInfo");
  538.  
  539.     ODBoolean result = kODFalse;
  540.  
  541.     SOM_TRY
  542.  
  543.     THROW_IF_NULL(facet, kODErrNullFacetInput);
  544.     THROW_IF_NULL(info, kODErrNullLinkInfoInput);
  545.     THROW_IF_NULL(infoResult, kODErrNullLinkInfoResultInput);
  546.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  547.  
  548.     ODSession* session = somSelf->GetStorageUnit(ev)->GetSession(ev);
  549.     ODTypeToken modalFocus = session->Tokenize(ev, kODModalFocus);
  550.     ODArbitrator* arbitrator = session->GetArbitrator(ev);
  551.     TempODFrame currentOwner = arbitrator->AcquireFocusOwner(ev, modalFocus);
  552.  
  553.     if ( arbitrator->RequestFocus(ev, modalFocus, facet->GetFrame(ev)) )
  554.     {
  555.         infoResult->autoUpdate = info->autoUpdate;
  556.     
  557.         session->GetWindowState(ev)->DeactivateFrontWindows(ev);
  558.  
  559.         result = ShowLinkDestinationInfo(somSelf, info, changesAllowed, infoResult);
  560.  
  561.         session->GetWindowState(ev)->ActivateFrontWindows(ev);
  562.  
  563.         arbitrator->TransferFocus(ev, modalFocus, facet->GetFrame(ev), currentOwner);
  564.     }
  565.     else
  566.     {
  567.         SysBeep(2);
  568.     }
  569.     return result;
  570.  
  571.     SOM_CATCH_ALL
  572.     SOM_ENDTRY
  573.     return kODFalse;
  574. }
  575.  
  576. //------------------------------------------------------------------------------
  577. // ODBaseLink: Lock
  578. //------------------------------------------------------------------------------
  579.  
  580. SOM_Scope ODBoolean  SOMLINK ODBaseLinkLock(ODBaseLink *somSelf, Environment *ev,
  581.         ODULong wait,
  582.         ODLinkKey* key)
  583. {
  584.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  585.     ODBaseLinkMethodDebug("ODBaseLink","Lock");
  586.  
  587.     SOM_TRY
  588.  
  589.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  590.  
  591.     return _fLinkSource->Lock(ev, wait, key);
  592.  
  593.     SOM_CATCH_ALL
  594.     SOM_ENDTRY
  595.     return kODFalse;
  596. }
  597.  
  598. //------------------------------------------------------------------------------
  599. // ODBaseLink: Unlock
  600. //------------------------------------------------------------------------------
  601.  
  602. SOM_Scope void  SOMLINK ODBaseLinkUnlock(ODBaseLink *somSelf, Environment *ev,
  603.         ODLinkKey key)
  604. {
  605.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  606.     ODBaseLinkMethodDebug("ODBaseLink","Unlock");
  607.  
  608.     SOM_TRY
  609.  
  610.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  611.  
  612.     _fLinkSource->Unlock(ev, key);
  613.  
  614.     SOM_CATCH_ALL
  615.     SOM_ENDTRY
  616. }
  617.  
  618. //------------------------------------------------------------------------------
  619. // ODBaseLink: KeyValid
  620. //------------------------------------------------------------------------------
  621.  
  622. SOM_Scope void  SOMLINK ODBaseLinkKeyValid(ODBaseLink *somSelf, Environment *ev,
  623.         ODLinkKey key)
  624. {
  625.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  626.     ODBaseLinkMethodDebug("ODBaseLink","KeyValid");
  627.  
  628.     SOM_TRY
  629.  
  630.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  631.  
  632.     _fLinkSource->KeyValid(ev, key);
  633.  
  634.     SOM_CATCH_ALL
  635.     SOM_ENDTRY
  636. }
  637.  
  638. //------------------------------------------------------------------------------
  639. // ODBaseLink: GetContentStorageUnit
  640. //------------------------------------------------------------------------------
  641.  
  642. SOM_Scope ODStorageUnit*  SOMLINK ODBaseLinkGetContentStorageUnit(ODBaseLink *somSelf, Environment *ev,
  643.         ODLinkKey key)
  644. {
  645.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  646.     ODBaseLinkMethodDebug("ODBaseLink","GetContentStorageUnit");
  647.  
  648.     SOM_TRY
  649.  
  650.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  651.  
  652.     if ( _fLinkSource->GetStatus(ev) == kODErrCannotEstablishLink )
  653.         THROW(kODErrCannotEstablishLink);
  654.  
  655.     ODStorageUnit* su = _fLinkSource->GetContentStorageUnit(ev, key);
  656.  
  657.     if ( su && !su->Exists(ev, kODPropContents, kODNULL, 1) )
  658.         THROW(kODErrNoLinkContent);
  659.  
  660.     return su;
  661.  
  662.     SOM_CATCH_ALL
  663.     SOM_ENDTRY
  664.     return (ODStorageUnit*) kODNULL;
  665. }
  666.  
  667. //------------------------------------------------------------------------------
  668. // ODBaseLink: RegisterDependent
  669. //------------------------------------------------------------------------------
  670.  
  671. SOM_Scope void  SOMLINK ODBaseLinkRegisterDependent(ODBaseLink *somSelf, Environment *ev,
  672.         ODPart* clientPart,
  673.         ODUpdateID id)
  674. {
  675.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  676.     ODBaseLinkMethodDebug("ODBaseLink","RegisterDependent");
  677.  
  678.     // This method does nothing if clientPart is already registered or
  679.     // if draft is read-only.
  680.  
  681.     SOM_TRY
  682.  
  683.         THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  684.     
  685.         THROW_IF_NULL(_fPartList, kODErrCannotRegisterDependent);
  686.  
  687.         ODDraftPermissions permissions = somSelf->GetStorageUnit(ev)->GetDraft(ev)->GetPermissions(ev);
  688.  
  689.         if (HAS_WRITE_ACCESS(permissions))
  690.         {
  691.             if ( _fPartList->AddPart(ev, clientPart) )
  692.             {
  693.                 ODUpdateID currentID = somSelf->GetUpdateID(ev);
  694.                 if ( (currentID != kODUnknownUpdate) && (id != currentID) )
  695.                     clientPart->LinkUpdated(ev, (ODLink*) somSelf, currentID);
  696.             }
  697.         }
  698.  
  699.     SOM_CATCH_ALL
  700.     
  701.     SOM_ENDTRY
  702. }
  703.  
  704. //------------------------------------------------------------------------------
  705. // ODBaseLink: UnregisterDependent
  706. //------------------------------------------------------------------------------
  707.  
  708. SOM_Scope void  SOMLINK ODBaseLinkUnregisterDependent(ODBaseLink *somSelf, Environment *ev,
  709.         ODPart* clientPart)
  710. {
  711.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  712.     ODBaseLinkMethodDebug("ODBaseLink","UnregisterDependent");
  713.  
  714.     SOM_TRY
  715.  
  716.         // If fPartList is null, this object's ReleaseAll() has been called
  717.         //   and already unregistered any dependents.
  718.         if ( _fPartList )
  719.             _fPartList->RemovePart(ev, clientPart);
  720.  
  721.     SOM_CATCH_ALL
  722.     
  723.     SOM_ENDTRY
  724. }
  725.  
  726. //------------------------------------------------------------------------------
  727. // ODBaseLink: GetUpdateID
  728. //------------------------------------------------------------------------------
  729.  
  730. SOM_Scope ODUpdateID  SOMLINK ODBaseLinkGetUpdateID(ODBaseLink *somSelf, Environment *ev)
  731. {
  732.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  733.     ODBaseLinkMethodDebug("ODBaseLink","GetUpdateID");
  734.  
  735.     SOM_TRY
  736.     
  737.     if ( _fLinkSource == (ODLinkSource*) kODNULL )
  738.         THROW(kODErrBrokenLink);
  739.  
  740.     return _fLinkSource->GetUpdateID(ev);
  741.  
  742.     SOM_CATCH_ALL
  743.     SOM_ENDTRY
  744.     return kODUnknownUpdate;
  745. }
  746.  
  747. //------------------------------------------------------------------------------
  748. // ODBaseLink: GetChangeTime
  749. //------------------------------------------------------------------------------
  750.  
  751. SOM_Scope ODTime  SOMLINK ODBaseLinkGetChangeTime(ODBaseLink *somSelf, Environment *ev)
  752. {
  753.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  754.     ODBaseLinkMethodDebug("ODBaseLink","GetChangeTime");
  755.     
  756.     SOM_TRY
  757.  
  758.     if ( _fLinkSource == (ODLinkSource*) kODNULL )
  759.         THROW(kODErrBrokenLink);
  760.  
  761.     return _fLinkSource->GetChangeTime(ev);
  762.     
  763.     SOM_CATCH_ALL
  764.     SOM_ENDTRY
  765.     return (ODTime)0;
  766. }
  767.  
  768. //------------------------------------------------------------------------------
  769. // ODBaseLink: SetLinkSource
  770. //------------------------------------------------------------------------------
  771.  
  772. SOM_Scope void  SOMLINK ODBaseLinkSetLinkSource(ODBaseLink *somSelf, Environment *ev,
  773.         ODLinkSource* linkSource)
  774. {
  775.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  776.     ODBaseLinkMethodDebug("ODBaseLink","SetLinkSource");
  777.  
  778.     SOM_TRY
  779.     
  780.     if ( !ODObjectsAreEqual(ev, _fLinkSource, linkSource) )
  781.     {
  782.         ODReleaseObject(ev, _fLinkSource);
  783.  
  784.         _fLinkSource = linkSource;
  785.         if ( _fLinkSource != (ODLinkSource*) kODNULL )
  786.             _fLinkSource->Acquire(ev);
  787.  
  788.         somSelf->SetBaseLinkDirty(ev);
  789.     }
  790.  
  791.     SOM_CATCH_ALL
  792.     SOM_ENDTRY
  793. }
  794.  
  795. //------------------------------------------------------------------------------
  796. // ODBaseLink: GetLinkSource
  797. //------------------------------------------------------------------------------
  798.  
  799. SOM_Scope ODLinkSource*  SOMLINK ODBaseLinkGetLinkSource(ODBaseLink *somSelf, Environment *ev)
  800. {
  801.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  802.     ODBaseLinkMethodDebug("ODBaseLink","GetLinkSource");
  803.  
  804.     if ( _fLinkSource == (ODLinkSource*) kODNULL )
  805.     {
  806.         ODSetSOMException(ev, kODErrBrokenLink);
  807.         return (ODLinkSource*) kODNULL;
  808.     }
  809.  
  810.     return _fLinkSource;
  811. }
  812.  
  813. //------------------------------------------------------------------------------
  814. // ODBaseLink: ShowSourceContent
  815. //------------------------------------------------------------------------------
  816.  
  817. SOM_Scope void  SOMLINK ODBaseLinkShowSourceContent(ODBaseLink *somSelf, Environment *ev)
  818. {
  819.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  820.     ODBaseLinkMethodDebug("ODBaseLink","ShowSourceContent");
  821.  
  822.     SOM_TRY
  823.  
  824.     THROW_IF_NULL(_fLinkSource, kODErrBrokenLink);
  825.  
  826.     _fLinkSource->ShowSourceContent(ev);
  827.  
  828.     SOM_CATCH_ALL
  829.     SOM_ENDTRY
  830. }
  831.  
  832. //------------------------------------------------------------------------------
  833. // ODBaseLink: UpdateDependents
  834. //------------------------------------------------------------------------------
  835.  
  836. SOM_Scope void  SOMLINK ODBaseLinkUpdateDependents(ODBaseLink *somSelf, Environment *ev)
  837. {
  838.     ODBaseLinkData *somThis = ODBaseLinkGetData(somSelf);
  839.     ODBaseLinkMethodDebug("ODBaseLink","UpdateDependents");
  840.  
  841.     if ( _fIterationInProgress )
  842.     {
  843.         _fRestartIteration = kODTrue;
  844.         return;
  845.     }
  846.  
  847.     _fIterationInProgress = kODTrue;
  848.  
  849.     SOM_TRY
  850.  
  851.         do
  852.         {
  853.             _fRestartIteration = kODFalse;
  854.     
  855.             ODPartList registeredParts;
  856.             registeredParts.AddPartList(ev, _fPartList);
  857.  
  858.             ODPartListIterator iter(®isteredParts);
  859.         
  860.             for (ODPart* clientPart = iter.First();
  861.                  !_fRestartIteration && iter.IsNotComplete();
  862.                  clientPart = iter.Next())
  863.             {
  864.                 // Don't call LinkUpdated if part has unregistered during iteration.
  865.                 if ( _fPartList->ContainsPart(ev, clientPart) )
  866.                 {
  867.                     // Ignore any errors returned from a part's LinkUpdated method
  868.                     TRY
  869.                         clientPart->LinkUpdated(ev, (ODLink*) somSelf, somSelf->GetUpdateID(ev));
  870.                     CATCH_ALL
  871.                     ENDTRY
  872.                 }
  873.             }
  874.             
  875.         } while ( _fRestartIteration );
  876.  
  877.     SOM_CATCH_ALL
  878.     
  879.     SOM_ENDTRY
  880.  
  881.     _fIterationInProgress = kODFalse;
  882. }
  883.